Previous Book Contents Book Index Next

Inside Macintosh: Mac OS 8 Toolbox Reference /
Chapter 2 - Control Manager Reference / Control Manager Functions
Defining Your Own Control Definition Function /


MyControlDefProc

CHANGED WITH THE APPEARANCE MANAGER

If you wish to define new, nonstandard controls for your application, you must write a control definition function and store it in a resource file as a resource of type 'CDEF'.

The Control Manager declares the type for an application-defined control definition function as follows:

typedef pascal SInt32 (*ControlDefProcPtr)
                     (SInt16 varCode, 
                      ControlHandle theControl, 
                      ControlDefProcMessage message, 
                      SInt32 param);
The Control Manager defines the data type ControlDefUPP to identify the universal procedure pointer for this application-defined function:

typedef UniversalProcPtr ControlDefUPP;
You typically use the NewControlDefProc macro like this:

ControlDefUPP myControlDefUPP;
myControlDefUPP = NewControlDefProc (MyControl);
You typically use the CallControlDefProc macro like this:

CallControlDefProc(myControlDefUPP, varCode, theControl, message, param);
Here's how to declare the function MyControlDefProc:

pascal SInt32 MyControlDefProc (
                     SInt16 varCode,
                     ControlHandle theControl,
                     ControlDefProcMessage message,
                     SInt32 param);
varCode
The control's variation code.
theControl
A handle to the control that the operation will affect.
message
A code for the task to be performed. The message parameter contains one of the task codes defined in "Messages". The subsections that follow explain each of these tasks in detail.
param
Data associated with the task specified by the message parameter. If the task requires no data, this parameter is ignored.
function result
The function results that your control definition function returns depend on the value that the Control Manager passes in the message parameter.
DISCUSSION
The Control Manager calls your control definition function under various circumstances; the Control Manager uses the message parameter to inform your control definition function what action it must perform. The data that the Control Manager passes in the param parameter, the action that your control definition function must undertake, and the function results that your control definition function returns all depend on the value that the Control Manager passes in the message parameter. The rest of this section describes how to respond to the various values that the Control Manager passes in the message parameter.

Messages

The Control Manager passes constants of type ControlDefProcMessage to indicate the action your control definition function must perform.

enum {
   drawCntl                     = 0,   
   testCntl                     = 1,   
   calcCRgns                    = 2,   
   initCntl                     = 3,   
   dispCntl                     = 4,   
   posCntl                      = 5,   
   thumbCntl                    = 6,   
   dragCntl                     = 7,   
   autoTrack                    = 8,   
   calcCntlRgn                  = 10,  
   calcThumbRgn                 = 11,
   kControlMsgDrawGhost         = 13, 
   kControlMsgCalcBestRect      = 14,
   kControlMsgHandleTracking    = 15,                
   kControlMsgFocus             = 16,  
   kControlMsgKeyDown           = 17,  
   kControlMsgIdle              = 18,
   kControlMsgGetFeatures       = 19,
   kControlMsgSetData           = 20,
   kControlMsgGetData           = 21,
   kControlMsgActivate          = 22,
   kControlMsgSetUpBackground   = 23,
   kControlMsgSubValueChanged   = 25,
   kControlMsgCalcValueFromPos  = 26,
   kControlMsgTestNewMsgSupport = 27,
   kControlMsgSubControlAdded   = 28,
   kControlMsgSubControlRemoved = 29
};
typedef SInt16 ControlDefProcMessage;

Constant descriptions

drawCntl
Draw the entire control or part of a control.
testCntl
Test where the mouse has been pressed.
calcCRgns
Calculate the region for the control or the indicator in 24-bit systems. This message is obsolete in Mac OS 7.6 and later.
initCntl
Perform additional control initialization.
dispCntl
Perform additional control disposal actions.
posCntl
Move and update the indicator setting.
thumbCntl
Calculate the parameters for dragging the indicator.
dragCntl
Perform customized dragging (of the control or its indicator).
autoTrack
Execute the specified action function.
calcCntlRgn
Calculate the control region in 32-bit systems.
calcThumbRgn
Calculate the indicator region in 32-bit systems.
kControlMsgDrawGhost
Draw a ghost image of the indicator.
kControlMsgCalcBestRect
Calculate the optimal control rectangle.
kControlMsgHandleTracking
Perform custom tracking.
kControlMsgFocus
Handle keyboard focus.
kControlMsgKeyDown
Handle keyboard events.
kControlMsgIdle
Perform idle processing.
kControlMsgGetFeatures
Specify which Appearance-compliant messages are supported.
kControlMsgSetData
Set control-specific data.
kControlMsgGetData
Get control-specific data.
kControlMsgActivate
Handle activate and deactivate events.
kControlMsgSetUpBackground
Set the control's background color or pattern (only available if the control supports embedding).
kControlMsgSubValueChanged
Be informed that the value of a subcontrol embedded in the control has changed; this message is useful for radio groups. Only available with Appearance 1.0.1 and later.
kControlMsgCalcValueFromPos
Support live feedback while dragging the indicator and calculate the control value based on the new indicator region.
kControlMsgTestNewMsgSupport
Specify whether Appearance-compliant messages are supported.
kControlMsgSubControlAdded
Be informed that a subcontrol has been embedded in the control. This message is only available with Appearance 1.0.1 and later.
kControlMsgSubControlRemoved
Be informed that a subcontrol is about to be removed from the control. This message is only available with Appearance 1.0.1 and later.
WHEN THE APPEARANCE MANAGER IS NOT AVAILABLE
Only the following messages will be sent to your control definition function:

   drawCntl             = 0,   
   testCntl             = 1,   
   calcCRgns            = 2,   
   initCntl             = 3,   
   dispCntl             = 4,   
   posCntl              = 5,   
   thumbCntl            = 6,   
   dragCntl             = 7,   
   autoTrack            = 8,   
   calcCntlRgn          = 10,  
   calcThumbRgn         = 11

Drawing the Control or Its Part

When the Control Manager passes the value drawCntl in the message parameter, your control definition function should respond by drawing the indicator or the entire control.

The Control Manager passes one of the following drawing constants in the low word of the param parameter to specify whether the user is drawing an indicator or the whole control. The high-order word of the param parameter may contain undefined data; therefore, evaluate only the low-order word of this parameter.

enum {
   kDrawControlEntireControl = 0, 
   kDrawControlIndicatorOnly = 129
};

Constant descriptions

kDrawControlEntireControl
Draw the entire control.
kDrawControlIndicatorOnly
Draw the indicator only.
With the exception of part code 128, which is reserved for future use and should not be used, any other value indicates a part code for the control.

If the specified control is visible, your control definition function should draw the control (or the part specified in the param parameter) within the control's rectangle. If the control is invisible (that is, if its contrlVis field is set to 0), your control definition function does nothing.

When drawing the control or its part, take into account the current values of its contrlHilite and contrlValue fields in the control structure.

If the part code for your control's indicator is passed in param, assume that the indicator hasn't moved; the Control Manager, for example, may be calling your control definition function so that you may simply highlight the indicator. However, when your application calls SetControlValue, SetControlMinimum, and SetControlMaximum, they in turn may call your control definition function with the drawCntl message to redraw the indicator. Since these functions have no way of determining what part code you chose for your indicator, they all pass 129 in param, meaning that you should move your indicator. Your control definition function must detect this part code as a special case and remove the indicator from its former location before drawing it. If your control has more than one indicator, you should interpret 129 to mean all indicators.

When sent the message drawCntl, your control definition function should return 0 as its function result.

Testing Where the Mouse-Down Event Occurs

When the Control Manager passes the value for the testCntl constant in the message parameter, your control definition function should respond by determining whether a specified point is in a visible control.

The Control Manager passes a point (in local coordinates) in the param parameter. The point's vertical coordinate is contained in the high-order word of the long integer, and horizontal coordinate is contained in the low-order word.

Your control definition function should return the part code of the part that contains the specified point; it should return 0 if the point is outside the control or if the control is inactive.

Calculating the Control and Indicator Regions on 24-Bit Systems

When the Control Manager passes the value for the calcCRgns constant in the message parameter, your control definition function should calculate the region passed in the param parameter for the specified control or its indicator.

The Control Manager passes a QuickDraw region handle in the param parameter. If the high-order bit of param is set, the region requested is that of the control's indicator; otherwise, the region requested is that of the entire control. Your control definition function should clear the high bit of the region handle before calculating the region.

When passed this message, your control definition function should always return 0, and it should express the region in the local coordinate system of the control's window.

IMPORTANT
The calcCRgns message will never be sent to any system running on 32-bit mode and is therefore obsolete in Mac OS 7.6 and later. The calcCntlRgn and calcThumbRgn messages will be sent instead.

Calculating the Control and Indicator Regions on 32-Bit Systems

When the Control Manager passes the values for the calcCntlRgn or calcThumbRgn constants in the message parameter, your control definition function should calculate the region for the specified control or its indicator using the QuickDraw region handle passed in the param parameter .

If the Control Manager passes the value for the calcThumbRgn constant in the message parameter, calculate the region occupied by the indicator. If the Control Manager passes the value for the calcCntlRgn constant in the message parameter, calculate the region for the entire control.

When passed this message, your control definition function should always return 0, and it should express the region in the local coordinate system of the control's window.

Performing Additional Control Initialization

After initializing fields of a control structure as appropriate when creating a new control, the Control Manager passes initCntl in the message parameter to give your control definition function the opportunity to perform any type-specific initialization you may require. For example, the standard control definition function for scroll bars allocates space for a region to hold the scroll box and stores the region handle in the contrlData field of the new control structure.

When passed the value for the initCntl constant in the message parameter, your control definition function should ignore the param parameter and return 0 as a function result.

Performing Additional Control Disposal Actions

The function DisposeControl passes dispCntl in the message parameter to give your control definition function the opportunity to carry out any additional actions when disposing of a control. For example, the standard definition function for scroll bars releases the memory occupied by the scroll box region, whose handle is kept in the contrlData field of the control structure.

When passed the value for the dispCntl constant in the message parameter, your control definition function should ignore the param parameter and return 0 as a function result.

Dragging the Control or Its Indicator

When a mouse-up event occurs in the indicator of a control, the HandleControlClick or TrackControl functions call your control definition function and pass posCntl in the message parameter. In this case, the Control Manager passes a point (in coordinates local to the control's window) in the param parameter that specifies the vertical and horizontal offset, in pixels, by which your control definition function should move the indicator from its current position. Typically, this is the offset between the points where the cursor was when the user pressed and released the mouse button while dragging the indicator. The point's vertical offset is contained in the high-order word of the param parameter, and its horizontal offset is contained in the low-order word.

Your definition function should calculate the control's new setting based on the
given offset and then, to reflect the new setting, redraw the control and update the contrlValue field in the control structure. Your control definition function should ignore the param parameter and return 0 as a function result.

Calculating Parameters for Dragging the Indicator

When the Control Manager passes the value for thumbCntl in the message parameter, your control definition function should respond by calculating values analogous to the limitRect, slopRect, and axis parameters of DragControl that constrain how the indicator is dragged. On entry, the fields param->limitRect.top and param->limitRect.left contain the point where the mouse-down event first occurred.

The Control Manager passes a pointer to a structure of type IndicatorDragConstraint in the param parameter:

struct IndicatorDragConstraint {
   Rect           limitRect;
   Rect           slopRect;
   DragConstraint axis;
};
typedef struct IndicatorDragConstraint IndicatorDragConstraint;
typedef IndicatorDragConstraint *IndicatorDragConstraintPtr;
typedef IndicatorDragConstraintPtr *IndicatorDragConstraintHandle;

Field Description
limitRect
A pointer to a rectangle--whose coordinates should normally coincide with or be contained in the window's content region--delimiting the area in which the user can drag the control's outline.
slopRect
A pointer to a rectangle that allows some extra space for the user to move the mouse while still constraining the control within the rectangle specified in the limitRect parameter.
axis
The axis along which the user may drag the control's outline.
Your definition function should store the appropriate values into the fields of the structure pointed to by the param parameter; they're analogous to the similarly named parameters of the Window Manager function DragGrayRgn .

Your control definition function should return 0 as function result.

Performing Custom Dragging

When the Control Manager passes the value for the dragCntl constant in the message parameter, the param parameter typically contains a custom dragging constant with one of the following values to specify whether the user is dragging an indicator or the whole control:

enum {
   kDragControlEntireControl = 0,
   kDragControlIndicator     = 1   
};

Constant descriptions

kDragControlEntireControl
Dragging the entire control.
kDragControlIndicator
Dragging the indicator.
Note
When the Appearance Manager is present, the message kControlMsgHandleTracking should be sent instead of dragCntl to handle any custom tracking; see "Performing Custom Tracking".
If you want to use the Control Manager's default method of dragging, which is to call DragControl to drag the control or the Window Manager function DragGrayRgn to drag its indicator, return 0 as the function result for your control definition function.

If your control definition function returns a nonzero value, your control definition function (not the Control Manager) must drag the specified control (or its indicator) to follow the cursor until the user releases the mouse button. If the user drags the entire control, your definition function should use the function MoveControl to reposition the control to its new location after the user releases the mouse button. If the user drags the indicator, your definition function must calculate the control's new setting (based on the pixel offset between the points where the cursor was when the user pressed and released the mouse button while dragging the indicator) and then, to reflect the new setting, redraw the control and update the contrlValue field in the control structure. Note that, in this case, the functions HandleControlClick and TrackControl return 0 whether or not the user changes the indicator's position. Thus, you must determine whether the user has changed the control's setting by another method, for instance, by comparing the control's value before and after the call to HandleControlClick.

Executing an Action Function

The only way to specify actions in response to all mouse-down events in a control or its indicator is to define your own control definition function that specifies an action function. When you create the control, your control definition function must first respond to the initCntl message by storing (ControlDefUPP)-1L in the contrlAction field of the control structure. (The Control Manager sends the initCntl message to your control definition function after initializing the fields of a new control structure.) Then, when your application passes (ControlActionUPP)-1L in the actionProc parameter of HandleControlClick or TrackControl, HandleControlClick calls your control definition function with the autoTrack message. The Control Manager passes the part code of the part where the mouse-down event occurs in the param parameter. Your control definition function should then use this information to respond as an action function would.

Note
For the autoTrack message, the high-order word of the param parameter may contain undefined data; therefore, evaluate only the low-order word of this parameter.
If the mouse-down event occurs in an indicator of a control that supports live feedback, your action function should take two parameters (a handle to the control and the part code of the control where the mouse-down event first occurred). This action function is the same one you would use to define actions to be performed in control part codes in response to a mouse-down event; see MyActionProc.

If the mouse-down event occurs in an indicator of a control that does not support live feedback, your action function should take no parameters, because the user may move the cursor outside the indicator while dragging it; see MyIndicatorActionProc.

Specifying Whether Appearance-Compliant Messages Are Supported

If your control definition function supports Appearance-compliant messages, it should return kControlSupportsNewMessages as a function result when the Control Manager passes kControlMsgTestNewMsgSupport in the message parameter.

enum{
   kControlSupportsNewMessages = ' ok '
};
Constant description

kControlSupportsNewMessages

The control definition function supports new messages introduced with Mac OS 8 and the Appearance Manager.

Specifying Which Appearance-Compliant Messages Are Supported

If your control definition function supports Appearance-compliant messages, it should return a bit field of the features it supports in response to the kControlMsgGetFeatures message. Your control definition function should ignore the param parameter.

The bit field returned by your control definition function should be composed of one or more of the following bits:

enum{
   kControlSupportsGhosting     = 1 << 0,
   kControlSupportsEmbedding    = 1 << 1,
   kControlSupportsFocus        = 1 << 2,
   kControlWantsIdle            = 1 << 3,
   kControlWantsActivate        = 1 << 4,
   kControlHandlesTracking      = 1 << 5,
   kControlSupportsDataAccess   = 1 << 6,
   kControlHasSpecialBackground = 1 << 7,
   kControlGetsFocusOnClick     = 1 << 8,
   kControlSupportsCalcBestRect = 1 << 9,
   kControlSupportsLiveFeedback = 1 << 10,
   kControlHasRadioBehavior     = 1 << 11
};

Constant descriptions

kControlSupportsGhosting
If this bit (bit 0) is set, the control definition function supports the kControlMsgDrawGhost message.
kControlSupportsEmbedding
If this bit (bit 1) is set, the control definition function supports the kControlMsgSubControlAdded and kControlMsgSubControlRemoved messages.
kControlSupportsFocus
If this bit (bit 2) is set, the control definition function supports the kControlMsgKeyDown message. If this bit and the kControlGetsFocusOnClick bit are set, the control definition function supports the kControlMsgFocus message.
kControlWantsIdle
If this bit (bit 3) is set, the control definition function supports the kControlMsgIdle message.
kControlWantsActivate
If this bit (bit 4) is set, the control definition function supports the kControlMsgActivate message.
kControlHandlesTracking
If this bit (bit 5) is set, the control definition function supports the kControlMsgHandleTracking message.
kControlSupportsDataAccess
If this bit (bit 6) is set, the control definition function supports the kControlMsgGetData and kControlMsgSetData messages.
kControlHasSpecialBackground
If this bit (bit 7) is set, the control definition function supports the kControlMsgSetUpBackground message.
kControlGetsFocusOnClick
If this bit (bit 8) and the kControlSupportsFocus bit are set, the control definition function supports the kControlMsgFocus message.
kControlSupportsCalcBestRect
If this bit (bit 9) is set, the control definition function supports the kControlMsgCalcBestRect message.
kControlSupportsLiveFeedback
If this bit (bit 10) is set, the control definition function supports the kControlMsgCalcValueFromPos message.
kControlHasRadioBehavior
If this bit (bit 11) is set, the control definition function supports radio button behavior and can be embedded in a radio group control. This constant is available with Appearance 1.0.1 and later.

Drawing a Ghost Image of the Indicator

If your control definition function supports indicator ghosting, it should return kControlSupportsGhosting as one of the feature bits in response to a kControlMsgGetFeatures message. If this bit is set and the control indicator is being tracked, the Control Manager calls your control definition function and passes kControlMsgDrawGhost in the message parameter. A handle to the region where the ghost should be drawn will be passed in the param parameter.

Your control definition function should respond by redrawing the control with the ghosted indicator at the specified location and should return 0 as its function result.

Note
The ghost indicator should always be drawn before the actual indicator so that it appears underneath the actual indicator.

Calculating the Optimal Control Rectangle

If your control definition function supports calculating the optimal dimensions of the control rectangle, it should return kControlSupportsCalcBestRect as one of the feature bits in response to the kControlMsgGetFeatures message. If this bit is set and GetBestControlRect is called, the Control Manager will call your control definition function and pass kControlMsgCalcBestRect in the message parameter. The Control Manager passes a pointer to a control size calculation structure in the param parameter.

Your control definition function should respond by calculating the width and height of the optimal control rectangle and adjusting the rectangle by setting the height and width fields of the control size calculation structure to the appropriate values. If your control definition function displays text, it should pass in the offset from the bottom of control to the base of the text in the baseLine field of the structure. Your control definition function should return the offset value stored in the structure's baseLine field.

The control size calculation structure is a structure of type ControlCalcSizeRec:

struct ControlCalcSizeRec {
   SInt16               height;
   SInt16               width;
   SInt16               baseLine;
};
typedef struct ControlCalcSizeRec ControlCalcSizeRec;
typedef ControlCalcSizeRec *ControlCalcSizePtr;

Field Description
height
The optimal height (in pixels) of the control's bounding rectangle.
width
The optimal width (in pixels) of the control's bounding rectangle.
baseLine
The offset from the bottom of the control to the base of the text. This value is generally negative.

Performing Custom Tracking

If your control definition function supports custom tracking, it should return kControlHandlesTracking as one of the feature bits in response to a kControlMsgGetFeatures message. If this bit is set and a mouse-down event occurs in your control, TrackControl or HandleControlClick calls your control definition function and passes kControlMsgHandlesTracking in the message parameter. The Control Manager passes a pointer to a control tracking structure in the param parameter. Your control definition function should respond appropriately and return the part code that was hit, or kControlNoPart if the mouse-down event occurred outside the control; see "Control Part Code Constants".

The control tracking structure is a structure of type ControlTrackingRec:

struct ControlTrackingRec {
   Point                startPt;
   SInt16               modifiers;
   ControlActionUPP     action;
};
typedef struct ControlTrackingRec ControlTrackingRec;
typedef ControlTrackingRec *ControlTrackingPtr;

Field Description
startPt
The location of the cursor at the time the mouse button was first pressed, in local coordinates. Your application retrieves this point from the where field of the event structure.
modifiers
The constant in the modifiers field of the event structure specifying the state of the modifier keys and the mouse button at the time the event was posted.
action
A pointer to an action function defining what action your application takes while the user holds down the mouse button. The value of the actionProc parameter can be a valid procPtr, nil, or -1. A value of -1 indicates that the control should either perform auto tracking, or if it is incapable of doing so, do nothing (like nil).

Handling Keyboard Focus

If your control definition function can change its keyboard focus, it should set kControlSupportsFocus and kControlGetsFocusOnClick as feature bits in response to a kControlMsgGetFeatures message. If these bits are set and the AdvanceKeyboardFocus, ReverseKeyboardFocus, ClearKeyboardFocus, or SetKeyboardFocus function is called, the Control Manager calls your control definition function and passes kControlMsgFocus in the message parameter.

The Control Manager passes one of the control focus part code constants described below or a valid part code in the param parameter. Your control definition function should respond by adjusting the focus accordingly.

Your control definition function should return the control focus part code or actual control part that was focused on. Return kControlFocusNoPart if your control does not accept focus or has just relinquished it. Return a nonzero part code to indicate that your control received keyboard focus. Your control definition function is responsible for maintaining which part is focused.

enum {                     
   kControlFocusNoPart   = 0,    
   kControlFocusNextPart = -1, 
   kControlFocusPrevPart = -2  
};
typedef SInt16 ControlFocusPart;

Constant descriptions

kControlFocusNoPart
Your control definition function should relinquish its focus and return kControlFocusNoPart. It might respond by deactivating its text edit handle and erasing its focus ring. If the control is at the end of its subparts, it should return kControlFocusNoPart. This tells the focusing mechanism to jump to the next control that supports focus.
kControlFocusNextPart
Your control definition function should change keyboard focus to its next part, the entire control, or remove keyboard focus from the control, depending upon the circumstances.
For multiple part controls that already had keyboard focus, the next part of the control would receive keyboard focus when kControlFocusNextPart was passed in the param parameter. For example, a clock control with keyboard focus would change its focus to the left-most element of the control (the month field).
For single-part controls that did not have keyboard focus and are now receiving it, the entire control would receive keyboard focus when kControlFocusNextPart was passed in the param parameter.
For single-part controls that already had keyboard focus and are now losing it, the entire control would lose keyboard focus.
If you are passed kControlFocusNextPart and have run out of parts, return kControlFocusNoPart to indicate that the user tabbed past the control.
kControlFocusPrevPart
Your control definition function should change keyboard focus to its previous part, the entire control, or remove keyboard focus from the control, depending upon the circumstances.
For multiple part controls that already had keyboard focus, the previous part of the control would receive keyboard focus when kControlFocusPrevPart was passed in the param parameter. For example, a clock control with keyboard focus would change its focus to the right-most element of the control (the year field).
For single-part controls that did not have keyboard focus and are now receiving it, the entire control would receive keyboard focus when kControlFocusNextPart was passed in the param parameter.
For single-part controls that already had keyboard focus and are now losing it, the entire control would lose keyboard focus.
If you are passed kControlFocusPrevPart and have run out of parts, return kControlFocusNoPart to indicate that the user tabbed past the control.
<part code>
Your control definition function should focus on the specified part code. Your function can interpret this in any way it wishes.

Handling Keyboard Events

If your control definition function can handle keyboard events, it should return kControlSupportsFocus--every control that supports keyboard focus must also be able to handle keyboard events--as one of the feature bits in response to a kControlMsgGetFeatures message. If this bit is set, the Control Manager will pass kControlMsgKeyDown in the message parameter. The Control Manager passes a pointer to a control key down structure in the param parameter. Your control definition function should respond by processing the keyboard event as appropriate and return 0 as the function result.

The control key down structure is a structure of type ControlKeyDownRec:

struct ControlKeyDownRec {
   SInt16               modifiers;
   SInt16               keyCode;
   SInt16               charCode;
};
typedef struct ControlKeyDownRec ControlKeyDownRec;
typedef ControlKeyDownRec *ControlKeyDownPtr;

Field Description
modifiers
The constant in the modifiers field of the event structure specifying the state of the modifier keys and the mouse button at the time the event was posted.
keyCode
The virtual key code derived from the event structure. This value represents the key pressed or released by the user. It is always the same for a specific physical key on a particular keyboard regardless of which modifier keys were also pressed.
charCode
A particular character derived from the event structure. This value depends on the virtual key code, the state of the modifier keys, and the current 'KCHR' resource.

Performing Idle Processing

If your control definition function can perform idle processing, it should return kControlWantsIdle as one of the feature bits in response to a kControlMsgGetFeatures message. If this bit is set and IdleControls is called for the window your control is in, the Control Manager will pass kControlMsgIdle in the message parameter. Your control definition function should ignore the param parameter and respond appropriately. For example, indeterminate progress indicators and asynchronous arrows use idle time to perform their animation.

Your control definition function should return 0 as the function result.

Getting and Setting Control-Specific Data

If your control definition function supports getting and setting control-specific data, it should return kControlSupportsDataAccess as one of its features bits in response to the kControlMsgGetFeatures message. If this bit is set, the Control Manager will call your control definition function and pass kControlMsgSetData in the message parameter when SetControlData is called, and will pass kControlMsgGetData in the message parameter when GetControlData and GetControlDataSize are called. The Control Manager passes a pointer to a control data access structure in the param parameter. Your definition function should respond by filling out the structure and returning an operating system status message as the function result.

The control data access structure is a structure of type ControlDataAccessRec: 
struct ControlDataAccessRec{
   ResType        tag;
   ResType        part;
   Size           size;
   Ptr            dataPtr;
};
typedef struct ControlDataAccessRec ControlDataAccessRec;
typedef ControlDataAccessRec *ControlDataAccessPtr;

Field Description
tag
A constant representing a piece of data that is passed in (in response to a kControlMsgSetData message) or returned (in response to a kControlMsgGetData message); see "Control Data Tag Constants" for a description of these constants. The control definition function should return errDataNotSupported if the value in the tag parameter is unknown or invalid.
part
The part of the control that this data should be applied to. If the information is not tied to a specific part of the control or the control has no parts, pass 0.
size
On entry, the size of the buffer pointed to by the dataPtr field. In response to a kControlMsgGetData message, this field should be adjusted to reflect the actual size of the data that the control is maintaining. If the size of the buffer being passed in is smaller than the actual size of the data, the control definition function should return errDataSizeMismatch.
dataPtr
A pointer to a buffer to read or write the information requested. In response to a kControlMsgGetData message, this field could be nil, indicating that you wish to return the size of the data in the size field.

Handling Activate and Deactivate Events

If your control definition function wants to be informed whenever it is being activated or deactivated, it should return kControlWantsActivate as one of the feature bits in response to the kControlMsgGetFeatures message. If this bit is set and your control definition function is being activated or deactivated, the Control Manager calls it and passes kControlMsgActivate in the message parameter. The Control Manager passes a 0 or 1 in the param parameter. A value of 0 indicates that the control is being deactivated; 1 indicates that it is being activated.

Your control definition function should respond by performing any special processing before the user pane becomes activated or deactivated, such as deactivating its TEHandle or ListHandle if it is about to be deactivated.

Your control definition function should return 0 as the function result.

Setting a Control's Background Color or Pattern

If your control definition function supports embedding and draws its own background, it should return kControlHasSpecialBackground as one of the feature bits in response to the kControlMsgGetFeatures message. If this bit is set and an embedding hierarchy of controls is being drawn in your control, the Control Manager passes kControlMsgSetUpBackground in the message parameter of your control definition function. The Control Manager passes a pointer to a filled-in control background structure in the param parameter. Your control definition function should respond by setting its background color or pattern to whatever is appropriate given the bit depth and device type passed in. Your control definition function should return 0 as the function result.

The control background structure is a structure of type ControlBackgroundRec:

struct ControlBackgroundRec {
   SInt16      depth;
   Boolean     colorDevice;
};
typedef struct ControlBackgroundRec ControlBackgroundRec;
typedef ControlBackgroundRec *ControlBackgroundPtr;

Field Description
depth
A signed 16-bit integer indicating the bit depth (in pixels) of the current graphics port.
colorDevice
A Boolean value. If true, you are drawing on a color device. If false, you are drawing on a monochrome device.

Supporting Live Feedback

If your control definition function supports live feedback while tracking the indicator, it should return kControlSupportsLiveFeedback as one of the feature bits in response to the kControlMsgGetFeatures message. If this bit is set, the Control Manager will call your control definition function when it tracks the indicator and pass kControlMsgCalcValueFromPos in the message parameter. The Control Manager passes a handle to the indicator region being dragged in the param parameter.

Your control definition function should respond by calculating its value and drawing the control based on the new indicator region passed in. Your control definition function should not recalculate its indicator position. After the user is done dragging the indicator, your control definition function will be called with a posCntl message at which time you can recalculate the position of the indicator. Not recalculating the indicator position each time your control definition function is called creates a smooth dragging experience for the user.

Your control definition function should return 0 as the function result.

Being Informed When Subcontrols Are Added or Removed

If your control definition function wishes to be informed when subcontrols are added or removed, it should return kControlSupportsEmbedding as one of the feature bits in response to the kControlMsgGetFeatures message. If this bit is set, the Control Manager passes ControlMsgSubControlAdded in the message parameter immediately after a subcontrol is added, or it passes kControlMsgSubControlRemoved just before a subcontrol is removed from your embedder control. A handle to the control being added or removed from the embedding hierarchy is passed in the param parameter. Your control definition function should respond appropriately and return 0 as the function result.

Typically, a control definition function only supports this message if it wants to do extra processing in response to changes in its embedded controls. Radio groups use these messages to perform necessary processing for handling embedded controls. For example, if a currently selected radio button is deleted, the group can adjust itself accordingly.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
8 JAN 1998